from __future__ import absolute_import, unicode_literals
from .celery import app


@app.task
def add(x, y):
    return x + y


@app.task
def mul(x, y):
    return x * y


@app.task
def xsum(numbers):
    return sum(numbers)


import logging
import csv
import scipy.misc
from os.path import exists
from os import mkdir
from scipy.ndimage.filters import median_filter
import matplotlib.pyplot as plt
import plotly.plotly as py
import numpy as np
from scipy.ndimage.morphology import binary_opening, binary_closing
import pbcvt
import xml.etree.ElementTree as et
import os
from scipy.signal import find_peaks_cwt

HOME_DIR = os.environ['HOME']
DB_ROOT = HOME_DIR + '/data/ddb1_v02_01/'
TRAIN_SET_FILE = HOME_DIR + '/data/ddb1_v02_01/ddb1_v02_01_train_plain.txt'
TEST_SET_FILE = HOME_DIR + '/data/ddb1_v02_01/ddb1_v02_01_test_plain.txt'
TMP_OUT = 'out_dir/'


@app.task
def imread(imgname):
    """Read image file form predifined file, To load different
    database, just need to change this function

    Args:
        imagename: name of the file, not the whole path
    Returns:
        Image read from the given name
    """
    img = scipy.misc.imread(DB_ROOT + imgname)
    img = img / 255
    return img


@app.task
def imsave(imagename, img, scale=False):
    """Save image file to folder defined in TMP_OUT
    Args:
        imagename: the output file name
        img: byte array of image
    Return:
        None
    """
    assert type(imagename) == str
    logging.info('save to ' + imagename)
    if not scale:
        img[img < 0] = 0
        img[img > 1] = 1
    scipy.misc.imsave(TMP_OUT + imagename + '.png', img)


@app.task
def vessel_seg(image):
    return pbcvt.vesselseg(image) > 0
    # return image


@app.task
def imsaveWithIndex(imagename, img, index=-1, scale=True):
    if index > -1:
        imsave('%d_%s' % (index, imagename), img, scale)


@app.task
def histgram(image):
    plt.hist(image)
    plt.title("Gaussian Histogram")
    plt.xlabel("Value")
    plt.ylabel("Frequency")
    fig = plt.gcf()
    plt.show()
    plot_url = py.plot_mpl(fig, filename='mpl-basic-histogram')
    print(plot_url)


@app.task
def candateSelection(image, tmpFileIndex=-1):
    """Generate candates of MA
    Args:
        image: image of fundus image
        tmpFileIndex: if larger than -1, than write tmp output image to file
    Returns:
        A list of tuples containing (row,col,radius) of MA center
    """
    invGreen = 1 - image[:, :, 1]
    imsaveWithIndex('0invGreen', invGreen, tmpFileIndex)
    bg = median_filter(invGreen, (25, 25), mode='nearest')
    imsaveWithIndex('1bg', bg, tmpFileIndex)
    sc = invGreen - bg
    imsaveWithIndex('2sc', sc, tmpFileIndex)
    cand = (sc > 0.01) + 0
    imsaveWithIndex('3cand', cand, tmpFileIndex)
    scale = 700 / image.shape[0];
    vessel = 1 - vessel_seg(scipy.misc.imresize(image, scale))
    # logging.info(vessel.max())
    vessel = scipy.misc.imresize(vessel, image.shape)
    imsaveWithIndex('4vessel', vessel, tmpFileIndex)
    # remove vessel
    vesselRemovel = cand * vessel
    imsaveWithIndex('5cand_remove_vessel', vesselRemovel, tmpFileIndex)
    result = binary_closing(vesselRemovel, np.ones((3, 3)))
    result = binary_opening(result, np.ones((3, 3)))
    imsaveWithIndex('6cand_opening', result, tmpFileIndex)
    return result


@app.task
def extractGroundTruth(xmlFileList):
    cord = []
    for file in xmlFileList:
        root = et.parse(DB_ROOT + file)
        markinglist = root.find('markinglist')
        for marking in markinglist.findall('marking'):
            markingtype = marking.find('markingtype')
            circleregion = marking.find('circleregion')
            if markingtype.text == 'Red_small_dots':
                # logging.info(markingtype.text)
                centroid = marking.find('.//centroid').find('coords2d')
                cordtext = centroid.text.split(',')
                cord.append((int(cordtext[1]), int(cordtext[0])))
    return cord


@app.task
def drawPoint(img, cord, length=20, shape='cross'):
    for c in cord:
        crow = c[0]
        ccol = c[1]
        for row in range(max(0, crow - length), min(img.shape[0], crow + length)):
            for col in range(max(0, ccol - length), min(ccol + length, img.shape[1])):
                dist = abs(ccol - col) + abs(crow - row)
                if not (row == crow or col == ccol):
                    continue
                if dist < 10:
                    continue
                img[row][col] = 1
    return img


_DFS_PATH = [
    # 4-connectivity
    (0, 1), (1, 0), (0, -1), (-1, 0),
    # 8-connectivity
    (1, 1), (1, -1), (-1, 1), (-1, -1)
]


@app.task
def minmax(arr, val):
    if arr[0] == -1:
        return val, val
    return min(val, arr[0]), max(val, arr[1])

@app.task
def getConnectedPert(image, connectivity=4):
    image = image > 0
    visisted = np.zeros(image.shape)
    index = 1
    areas = []
    areas.push(ConnectionStatus(0))

    def dfs(row, col):
        if visisted[row, col]:
            return
        for dr, dc in _DFS_PATH[:connectivity]:
            r = row + dr
            c = col + dc
            if (visisted[r, c] == 0):
                visisted[r, c] = 1
                areas[-1].add(r, c)
                dfs(r, c)

    for row in range(image.shape[0]):
        for col in range(image.shape[1]):
            if image[row, col]:
                if visisted[row, col] == 0:
                    areas.push(ConnectionStatus(index))
                    index += 1
                    dfs(col, row)
    for i in range(1, len(areas)):
        areas[i].finish()
    return areas[1:]


@app.task
def eval(segment, coord):
    dectWidth = 5
    TP = 0.0
    for cr, cc in coord:
        # t = False
        patch = segment[
                max(0, cr - dectWidth): min(segment.shape[0], cr + dectWidth),
                max(0, cc - dectWidth): min(segment.shape[1], cc + dectWidth)
                ]
        if patch.sum():
            TP += 1.0
        else:
            logging.warning((cr, cc))
            # for row in range():
            #     for col in range(max(0, cc - dectWidth), min(segment.shape[1], cc + dectWidth)):
            #         if segment[row, col]:
            #             TP += 1
            #             t = True
            #             break
            #     if t:
            #         break
    logging.info('ALL MARKS:%d Labeled : %d ' % (len(coord), TP))
    if len(coord) == 0:
        return 1
    return TP / float(len(coord))
